import datetime
import time

import json

import asyncio

import okex.futures_api as future
import okex.spot_api as spot
from . import ws
from huobi_future.HuobiDMService import HuobiDM
from huobi import RequestClient
from bfxapi import Client as BFXClient

okex_api_key = '82d7b8fc-b9f6-4a72-9b74-572329cf7f56'
okex_seceret_key = '3C73FA9B7B1B18B417A92D3CF653FF82'
okex_passphrase = 'banbanpepp'

# 要请求的币
stock_ticker_list = ['BTC-USDT', 'ETH-USDT', 'ETC-USDT', 'BSV-USDT', 'XRP-USDT', 'EOS-USDT', 'BCH-USDT']

huobi_url = 'https://api.hbdm.com/'
huobi_access_key = ''
huobi_secret_key = ''

# ok现货api
spotAPI = spot.SpotAPI(okex_api_key, okex_seceret_key, okex_passphrase, True)
# ok合约api
futureAPI = future.FutureAPI(okex_api_key, okex_seceret_key, okex_passphrase, True)

# 火币现货api
hbClient = RequestClient()
# 火币合约api
dm = HuobiDM(huobi_url, huobi_access_key, huobi_secret_key)

# bfx现货api
bfx = BFXClient(
    logLevel='DEBUG'
)


# 用于计算形式为‘090612’的日期格式与当天之间的天数差值
def time_gap_from_today(timeStr):
    date = datetime.datetime.strptime("20" + timeStr, '%Y%m%d')
    today = datetime.datetime.today()
    return (date - today).days


def fetch_bfx_stock(ticker):
    return [ticker[0], ticker[-4]]


def fetch_ok_stock(ticker):
    return [ticker['instrument_id'], ticker['last']]


def ok_to_bfx(str):
    """
    BTC-USDT 转为 tBTCUSD
    :param str:
    :return:
    """
    return 't' + str[:-1].replace('-', '')

def ok_to_hb(str):
    """
    BTC-USDT 转为 btcusdt
    :param str:
    :return:
    """
    return str.replace("-", "").lower()

def get_need_coin(ticker):
    if ticker['instrument_id'][:-7] + 'T' in stock_ticker_list:
        return ticker

def get_stock_need_coin(ticker):
    if ticker['instrument_id'] in stock_ticker_list:
        return ticker

# 计算okex自身平台中现货与期货的溢价计算
def okex_okex_future_stock(sc):
    time.sleep(2)
    # 期货
    all_ok_future_ticker = futureAPI.get_ticker()
    ok_future_tickers = list(filter(get_need_coin, all_ok_future_ticker))
    # 现货
    all_stock_ticker = spotAPI.get_ticker()
    ok_stock_tickers = list(filter(get_stock_need_coin, all_stock_ticker))
    # 提取需要的字段转为map
    ok_stock_price_list = list(map(fetch_ok_stock, ok_stock_tickers))
    ok_stock_price_dict = dict(ok_stock_price_list)
    response = []
    # 遍历ok期货
    for ok_future in ok_future_tickers:
        instrument_id = ok_future['instrument_id'][:-7] + 'T'
        if instrument_id in stock_ticker_list:
            f = float(ok_future['last'])
            if instrument_id in ok_stock_price_dict.keys():
                stock = float(ok_stock_price_dict[instrument_id])
            else:
                # 获取不到某个币
                stock = f
            diff = f - stock
            result = diff / stock
            gap = time_gap_from_today(ok_future['instrument_id'][-6:])
            _type = ""
            if gap <= 9:
                _type = 'THIS'
            elif gap > 9 and gap <= 14:
                _type = 'NEXT'
            else:
                _type = 'QUARTER'
            res = {
                "token": instrument_id[:-5],
                "stock_instrument_id": instrument_id,
                "future_instrument_id": ok_future['instrument_id'],
                "diff": diff,
                "result": result,
                "stock": stock,
                "future": f,
                "type": _type
            }
            response.append(res)
    resp = {
        "channel": "okex-okex",
        "data": response
    }
    sc.send(json.dumps(resp))


def okex_bfx_future_stock(sc):
    """
    okex现货的返回  https://docs.bitfinex.com/v2/reference#rest-public-ticker
    [
        "tBTCUSD",
        7990,
        37.032208589999996,
        7990.1,
        19.938810020000002,
        180.1,
        0.0231,
        7990.1,  这是现货价格
        10070.30191133,
        8018,
        7455
    ]
    """
    time.sleep(2)
    all_ok_future_ticker = futureAPI.get_ticker()
    ok_future_tickers = list(filter(get_need_coin, all_ok_future_ticker))
    # print(ok_future_tickers)
    # 由于bfx请求的币的格式为 tBTCUSD, tEOSUSD，这里转换下
    bfx_req_ticker_list = list(map(ok_to_bfx, stock_ticker_list))
    # 获取所有的现货
    bfx_all_stock_ticker = asyncio.get_event_loop().run_until_complete(bfx.rest.get_public_tickers(bfx_req_ticker_list))
    # 对现货进行处理，转为map存储
    bfx_stock_price_list = list(map(fetch_bfx_stock, bfx_all_stock_ticker))
    bfx_stock_price_dict = dict(bfx_stock_price_list)
    # print(bfx_stock_price_map)
    response = []
    # 遍历ok期货
    for ok_future in ok_future_tickers:
        instrument_id = ok_future['instrument_id'][:-7] + 'T'
        if instrument_id in stock_ticker_list:
            f = float(ok_future['last'])
            key = ok_to_bfx(instrument_id)
            if key in bfx_stock_price_dict.keys():
                stock = float(bfx_stock_price_dict[key])

            else:
                # 获取不到某个币，如bchusd
                stock = f
            diff = f - stock
            result = diff / stock
            gap = time_gap_from_today(ok_future['instrument_id'][-6:])
            _type = ""
            if gap <= 7:
                _type = 'THIS'
            elif gap > 7 and gap <= 14:
                _type = 'NEXT'
            else:
                _type = 'QUARTER'
            res = {
                "token": instrument_id[:-5],
                "stock_instrument_id": instrument_id,
                "future_instrument_id": ok_future['instrument_id'],
                "diff": diff,
                "result": result,
                "stock": stock,
                "future": f,
                "type": _type
            }
            response.append(res)
        resp = {
            "channel": "okex-bfx",
            "data": response
        }
    sc.send(json.dumps(resp))


def okex_hb_future_stock(sc):
    """
    huobi现货返回 https://api.huobi.pro/market/trade?symbol=ethusdt
    {
        "id": 600848670,
        "ts": 1489464451000,
        "data": [
        {
            "id": 600848670,
            "price": 7962.62,
            "amount": 0.0122,
            "direction": "buy",
            "ts": 1489464451000
        }
        ]
    }
    """
    all_ok_future_ticker = futureAPI.get_ticker()
    ok_future_tickers = list(filter(get_need_coin, all_ok_future_ticker))
    # 由于huobi的symbol格式是ethusdt，转化一下
    hb_req_ticker_list = list(map(ok_to_hb, stock_ticker_list))
    # 获取huobi上面对应的现货价格，并构建json
    hb_stock_price_dict = {}
    for symbol in hb_req_ticker_list:
        try:
            trade = hbClient.get_last_trade(symbol)
            hb_stock_price_dict.update({symbol: trade.price})
        except:
            pass # 如果出现请求失败则跳过
        time.sleep(0.05) # 由于huobi请求现货是分开请求，请求间隔太小会被限制，做一个等待

    response = []
    # 遍历ok期货
    for ok_future in ok_future_tickers:
        instrument_id = ok_future['instrument_id'][:-7] + 'T'
        if instrument_id in stock_ticker_list:
            f = float(ok_future['last'])
            key = ok_to_hb(instrument_id)
            if key in hb_stock_price_dict.keys():
                stock = float(hb_stock_price_dict[key])

            else:
                # 获取不到某个币，如bchusd
                stock = f
            diff = f - stock
            result = diff / stock
            gap = time_gap_from_today(ok_future['instrument_id'][-6:])
            _type = ""
            if gap <= 7:
                _type = 'THIS'
            elif gap > 7 and gap <= 14:
                _type = 'NEXT'
            else:
                _type = 'QUARTER'
            res = {
                "token": instrument_id[:-5],
                "stock_instrument_id": instrument_id,
                "future_instrument_id": ok_future['instrument_id'],
                "diff": diff,
                "result": result,
                "stock": stock,
                "future": f,
                "type": _type
            }
            response.append(res)
        resp = {
            "channel": "okex-huobi",
            "data": response
        }
    sc.send(json.dumps(resp))
    time.sleep(2)


def huobi_okex_future_stock(sc):
    time.sleep(2)
    # 获取okex现货价格
    all_stock_ticker = spotAPI.get_ticker()
    stock_tickers = []
    for ticker in all_stock_ticker:
        if ticker['instrument_id'] in stock_ticker_list:
            stock_tickers.append({
                'instrument_id': ticker['instrument_id'],
                'last': ticker['last']
            })
    # 获取huobi期货价格
    response = []
    for ticker in stock_tickers:
        instrument_id = ticker['instrument_id']
        token_name = ticker['instrument_id'][:-5]
        okex_stock = float(ticker['last'])
        print("获取期货\n")
        cw = dm.get_contract_trade(token_name + '_CW')
        cw_future_price = float(cw['tick']['data'][0]['price'])
        diff = cw_future_price - okex_stock
        result = diff / okex_stock
        res_cw = {
            "token": instrument_id,
            "stock_instrument_id": instrument_id,
            "future_instrument_id": token_name,
            "diff": diff,
            "result": result,
            "stock": okex_stock,
            "future": cw_future_price,
            "type": 'THIS'
        }
        nw = dm.get_contract_trade(token_name + '_NW')
        nw_future_price = float(nw['tick']['data'][0]['price'])
        diff = nw_future_price - okex_stock
        result = diff  / okex_stock
        res_nw = {
            "token": instrument_id,
            "stock_instrument_id": instrument_id,
            "future_instrument_id": token_name,
            "diff": diff,
            "result": result,
            "stock": okex_stock,
            "future": nw_future_price,
            "type": 'NEXT'
        }
        cq = dm.get_contract_trade(token_name + '_CQ')
        cq_future_price = float(cq['tick']['data'][0]['price'])
        diff = cq_future_price - okex_stock
        result = diff * 100 / okex_stock
        res_cq = {
            "token": instrument_id,
            "stock_instrument_id": instrument_id,
            "future_instrument_id": token_name,
            "diff": diff,
            "result": result,
            "stock": okex_stock,
            "future": cq_future_price,
            "type": 'QUARTER'
        }
        response.append(res_cw)
        response.append(res_nw)
        response.append(res_cq)
    print(json.dumps(response), '\n')
    sc.send(json.dumps(response))


def hb_hb_future_stock(sc):
    pass


def hb_bfx_future_stock(sc):
    pass


def bfx_okex_future_stock(sc):
    pass


def bfx_hb_future_stock(sc):
    pass


def bfx_bfx_future_stock(sc):
    pass




@ws.route("/okex")
def okex_connect(socket):
    while not socket.closed:
        okex_okex_future_stock(socket)
        okex_bfx_future_stock(socket)
        okex_hb_future_stock(socket)


@ws.route("/huobi-okex")
def huobi_okex(socket):
    while not socket.closed:
        huobi_okex_future_stock(socket)

# @ws.route("/okex-bfx")
# def okex_bfx(socket):
#     while not socket.closed:
#         time.sleep(4)
#         okex_bfx_future_stock(socket)
